package com.ai.wx.handler;




import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ai.core.util.Configure;
import com.ai.wx.util.MD5Util;
import com.ai.wx.util.Sha1Util;
import com.ai.wx.util.TenpayUtil;



/*
 '微信支付服务器签名支付请求请求类
 '============================================================================
 'api说明：
 'init(app_id, app_secret, partner_key, app_key);
 '初始化函数，默认给一些参数赋值，如cmdno,date等。
 'setKey(key_)'设置商户密钥
 'getLasterrCode(),获取最后错误号
 'GetToken();获取Token
 'getTokenReal();Token过期后实时获取Token
 'createMd5Sign(signParams);生成Md5签名
 'genPackage(packageParams);获取package包
 'createSHA1Sign(signParams);创建签名SHA1
 'sendPrepay(packageParams);提交预支付
 'getDebugInfo(),获取debug信息
 '============================================================================
 '*/
public class RequestHandler {
	/** Token获取网关地址地址 */
	private String tokenUrl;
	/** 预支付网关url地址 */
	private String gateUrl;
	/** 查询支付通知网关URL */
	private String notifyUrl;
	/** 商户参数 */
	private String appid;
	private String appkey;
	private String partnerkey;
	private String appsecret;
	private String key;
	/** 请求的参数 */
	private SortedMap parameters;
	/** Token */
	private String Token;
	private String charset;
	/** debug信息 */
	private String debugInfo;
	private String last_errcode;

	private HttpServletRequest request;

	private HttpServletResponse response;

	/**
	 * 初始构造函数。
	 * 
	 * @return
	 */
	public RequestHandler(HttpServletRequest request,
			HttpServletResponse response) {
		this.last_errcode = "0";
		this.request = request;
		this.response = response;
		//this.charset = "GBK";
		this.charset = "UTF-8";
		this.parameters = new TreeMap();
		// 验证notify支付订单网关
		notifyUrl = "https://gw.tenpay.com/gateway/simpleverifynotifyid.xml";
		this.init(Configure.getAppId(),Configure.getAppsecret(),Configure.getPartner());
	}

	/**
	 * 初始化函数。
	 */
	public void init(String app_id, String app_secret,	String partner_key) {
		this.last_errcode = "0";
		this.Token = "token_";
		this.debugInfo = "";
		this.appid = app_id;
		this.partnerkey = partner_key;
		this.appsecret = app_secret;
		this.key = partner_key;
	}

	public void init() {
	}

	/**
	 * 获取最后错误号
	 */
	public String getLasterrCode() {
		return last_errcode;
	}

	/**
	 *获取入口地址,不包含参数值
	 */
	public String getGateUrl() {
		return gateUrl;
	}

	/**
	 * 获取参数值
	 * 
	 * @param parameter
	 *            参数名称
	 * @return String
	 */
	public String getParameter(String parameter) {
		String s = (String) this.parameters.get(parameter);
		return (null == s) ? "" : s;
	}

	
	 //设置密钥
	
	public void setKey(String key) {
		this.key = key; 
	}
	//设置微信密钥
	public void  setAppKey(String key){
		this.appkey = key;
	}
	
	// 特殊字符处理
	public String UrlEncode(String src) throws UnsupportedEncodingException {
		return URLEncoder.encode(src, this.charset).replace("+", "%20");
	}

	// 获取package的签名包
	public String genPackage(SortedMap<String, String> packageParams)
			throws UnsupportedEncodingException {
		String sign = createSign(packageParams);

		StringBuffer sb = new StringBuffer();
		Set es = packageParams.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			sb.append(k + "=" + UrlEncode(v) + "&");
		}

		// 去掉最后一个&
		String packageValue = sb.append("sign=" + sign).toString();
//		System.out.println("UrlEncode后 packageValue=" + packageValue);
		return packageValue;
	}

	/**
	 * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
	 */
	public String createSign(SortedMap<String, String> packageParams) {
		StringBuffer sb = new StringBuffer();
		Set es = packageParams.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			if (null != v && !"".equals(v) && !"sign".equals(k)
					&& !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + this.getKey());
 		System.out.println("md5 sb:" + sb);
		String sign = MD5Util.MD5Encode(sb.toString(), this.charset)
				.toUpperCase();
		System.out.println("packge签名:" + sign);
		return sign;

	}
	/**
	 * 创建package签名
	 */
	public boolean createMd5Sign(String signParams) {
		StringBuffer sb = new StringBuffer();
		Set es = this.parameters.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			if (!"sign".equals(k) && null != v && !"".equals(v)) {
				sb.append(k + "=" + v + "&");
			}
		}

		// 算出摘要
		String enc = TenpayUtil.getCharacterEncoding(this.request,
				this.response);
		String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();

		String tenpaySign = this.getParameter("sign").toLowerCase();

		// debug信息
		this.setDebugInfo(sb.toString() + " => sign:" + sign + " tenpaySign:"
				+ tenpaySign);

		return tenpaySign.equals(sign);
	}

    //输出XML
	   public String parseXML() {
		   StringBuffer sb = new StringBuffer();
	       sb.append("<xml>");
	       Set es = this.parameters.entrySet();
	       Iterator it = es.iterator();
	       while(it.hasNext()) {
				Map.Entry entry = (Map.Entry)it.next();
				String k = (String)entry.getKey();
				String v = (String)entry.getValue();
				if(null != v && !"".equals(v) && !"appkey".equals(k)) {
					
					sb.append("<" + k +">" + getParameter(k) + "</" + k + ">\n");
				}
			}
	       sb.append("</xml>");
			return sb.toString();
		}

	/**
	 * 设置debug信息
	 */
	protected void setDebugInfo(String debugInfo) {
		this.debugInfo = debugInfo;
	}
	public void setPartnerkey(String partnerkey) {
		this.partnerkey = partnerkey;
	}
	public String getDebugInfo() {
		return debugInfo;
	}
	public String getKey() {
		return key;
	}

	
	
	
	
	public  SortedMap<String, String> buildPackageMap(String openid,String orderPrice, String outTradeNo, String productName,String remoteIp) {
	    // 设置package订单参数
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
//		packageParams.put("bank_type", "WX"); // 支付类型
//		packageParams.put("body", productName); // 商品描述
//		packageParams.put("fee_type", "1"); // 银行币种
//		packageParams.put("input_charset", "UTF-8"); // 字符集
//		packageParams.put("notify_url", Configure.getNotifyUrl()); // 通知地址
//		packageParams.put("out_trade_no", outTradeNo); // 商户订单号
//		packageParams.put("partner", Configure.getPartner()); // 设置商户号
//		packageParams.put("total_fee", orderPrice); // 商品总金额,以分为单位
//		packageParams.put("spbill_create_ip", remoteIp); // 订单生成的机器IP，指用户浏览器端IP
		
		
		
		packageParams.put("appid", Configure.getAppId());  
		packageParams.put("mch_id", Configure.getPartner());  
		packageParams.put("nonce_str", Sha1Util.getNonceStr());  
		packageParams.put("body", productName);  
		//packageParams.put("attach", attach);  
		packageParams.put("out_trade_no", outTradeNo);  
		
		
		//这里写的金额为1 分到时修改
		packageParams.put("total_fee", orderPrice);  
 		packageParams.put("spbill_create_ip", remoteIp);  
		packageParams.put("notify_url", Configure.getNotifyUrl());  
		
		packageParams.put("trade_type", "JSAPI");  
		packageParams.put("openid", openid);  
		
		String sign = createSign(packageParams);

		packageParams.put("sign", sign);  
	    return packageParams;
    }
	
	public  String buildOutTradeNo(){

		// 当前时间 yyyyMMddHHmmss
		String currTime = TenpayUtil.getCurrTime();
		// 8位日期
		String strTime = currTime.substring(8, currTime.length());
		// 四位随机数
		String strRandom = TenpayUtil.buildRandom(4) + "";
		// 10位序列号,可以自行调整。
		String strReq = strTime + strRandom;
		// 订单号，此处用时间加随机数生成，商户根据自己情况调整，只要保持全局唯一就行
		return strReq;
	}
	
	

	public SortedMap<String, String> buildPaySignMap(String prepayId) throws Exception {
	    SortedMap<String, String> signParams = new TreeMap<String, String>();
		signParams.put("appId", Configure.getAppId());
		signParams.put("nonceStr", Sha1Util.getNonceStr());
		signParams.put("package", "prepay_id="+prepayId);
		signParams.put("timeStamp", Sha1Util.getTimeStamp());
		signParams.put("signType", "MD5");
		// 生成支付签名，要采用URLENCODER的原始值进行SHA1算法！
		String sign = createSign(signParams);

		// 增加非参与签名的额外参数
		signParams.put("paySign", sign);
	    return signParams;
    }
	
	
	
//	public String createPostXml(SortedMap<String, String> packageParams) {
//		String sign = createSign(packageParams);
////		String xml="<xml>"+
////				"<appid>"+packageParams.get("appid")+"</appid>"+
////				"<mch_id>"+packageParams.get("mch_id")+"</mch_id>"+
////				"<nonce_str>"+packageParams.get("nonce_str")+"</nonce_str>"+
////				"<sign>"+sign+"</sign>"+
////				"<body><![CDATA["+packageParams.get("body")+"]]></body>"+
////				//"<attach>"+packageParams.get("attach")+"</attach>"+
////				"<out_trade_no>"+packageParams.get("out_trade_no")+"</out_trade_no>"+  
////				"<total_fee>"+packageParams.get("total_fee")+"</total_fee>"+ 
////				"<spbill_create_ip>"+packageParams.get("spbill_create_ip")+"</spbill_create_ip>"+
////				"<notify_url>"+packageParams.get("notify_url")+"</notify_url>"+
////				"<trade_type>"+packageParams.get("trade_type")+"</trade_type>"+
////				"<openid>"+packageParams.get("openid")+"</openid>"+
////				"</xml>";
//		
////		System.out.println(xml);
//		return xml;
//	}
	
	public static String getRequestXml(SortedMap<String,String> parameters){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            String v = (String)entry.getValue();
            if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) {
                sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
            }else {
                sb.append("<"+k+">"+v+"</"+k+">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }
	
	/**
	 * @author 李欣桦
	 * @date 2014-12-3上午10:17:43
	 * @Description：返回给微信的参数
	 * @param return_code 返回编码
	 * @param return_msg  返回信息
	 * @return
	 */
	public static String setXML(String return_code, String return_msg) {
		return "<xml><return_code><![CDATA[" + return_code
				+ "]]></return_code><return_msg><![CDATA[" + return_msg
				+ "]]></return_msg></xml>";
	}
}
